package com.zsk.shop.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsk.shop.common.base.BaseResponse;
import com.zsk.shop.common.base.BizExceptionEnum;
import com.zsk.shop.common.base.NoMsgException;
import com.zsk.shop.common.constant.Constant;
import com.zsk.shop.common.utils.PageWithSqlUtil;
import com.zsk.shop.common.utils.EntityConvertUtils;
import com.zsk.shop.common.utils.HttpContext;
import com.zsk.shop.common.utils.ToolUtil;
import com.zsk.shop.entity.GopMenu;
import com.zsk.shop.entity.GopRole;
import com.zsk.shop.entity.GopRoleMenuRelation;
import com.zsk.shop.mapper.GopRoleMapper;
import com.zsk.shop.model.params.GopRoleAddParam;
import com.zsk.shop.model.params.GopRoleEditParam;
import com.zsk.shop.model.results.GopRoleResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author stylefeng
 * @since 2018-12-07
 */
@Service
@DS("master")
public class GopRoleService extends ServiceImpl<GopRoleMapper, GopRole> {

    @Resource
    private GopRelationService relationService;

    @Autowired
    private GopMenuService menuService;

    /**
     * 添加角色
     *
     * @author fengshuonan
     * @Date 2018/12/23 6:40 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse addRole(GopRoleAddParam param) {
        if (ToolUtil.isOneEmpty(param, param.getName())) {
            throw new NoMsgException(400, "参数不完整");
        }
        if (queryHaveByRoleName(param.getName(), null)) {
            return BaseResponse.error("当前角色名称和已有名称重复");
        }
        GopRole gopRole = EntityConvertUtils.convertAToB(param, GopRole.class);
        if (ToolUtil.isEmpty(param.getDescription())) {
            gopRole.setDescription("");
        }
        gopRole.setCreateUser(HttpContext.getUserId());
        gopRole.setUpdateUser(HttpContext.getUserId());
        gopRole.setCreateTime(new Date());
        gopRole.setUpdateTime(new Date());
        return BaseResponse.success(this.save(gopRole));
    }

    //查询角色名是否重复
    private boolean queryHaveByRoleName(String name, Long id) {
        LambdaQueryWrapper<GopRole> queryWrapper = new LambdaQueryWrapper<>();
        if (ToolUtil.isNotEmpty(id)) {
            queryWrapper.ne(GopRole::getId, id);
        }
        queryWrapper.eq(GopRole::getName, name);
        queryWrapper.last("limit 1");
        if (ToolUtil.isNotEmpty(this.getOne(queryWrapper))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 编辑角色
     *
     * @author fengshuonan
     * @Date 2018/12/23 6:40 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse editRole(GopRoleEditParam param) {
        if (ToolUtil.isOneEmpty(param, param.getId(), param.getName(), param.getSort())) {
            throw new NoMsgException(400, "参数不完整");
        }
        if (queryHaveByRoleName(param.getName(), param.getId())) {
            return BaseResponse.error("当前角色名称和已有名称重复");
        }
        GopRole old = this.getById(param.getId());
        if (ToolUtil.isEmpty(old)) {
            return BaseResponse.error("当前角色数据不存在");
        }
        BeanUtil.copyProperties(param, old);
        old.setUpdateUser(HttpContext.getUserId());
        old.setUpdateTime(new Date());
        return BaseResponse.success(this.updateById(old));
    }

    /**
     * 设置某个角色的权限
     *
     * @param roleId 角色id
     * @param ids    权限的id
     * @date 2017年2月13日 下午8:26:53
     */
    @Transactional(rollbackFor = Exception.class)
    public void setAuthority(Long roleId, String ids) {
        // 删除该角色所有的权限
        this.baseMapper.deleteRolesById(roleId);
        // 添加新的权限
        for (Long id : Convert.toLongArray(ids.split(","))) {
            GopRoleMenuRelation relation = new GopRoleMenuRelation();
            relation.setRoleId(roleId);
            relation.setMenuId(id);
            this.relationService.getBaseMapper().insert(relation);
        }
    }

    /**
     * 删除角色
     *
     * @author stylefeng
     * @Date 2017/5/5 22:24
     */
    @Transactional(rollbackFor = Exception.class)
    public void delRoleById(Long roleId) {
        if (ToolUtil.isEmpty(roleId)) {
            throw new NoMsgException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能删除超级管理员角色
        if (roleId.equals(Constant.GOP_ADMIN_ROLE_ID)) {
            throw new NoMsgException(BizExceptionEnum.CANT_DELETE_ADMIN);
        }
        //删除该角色所有的权限
        this.baseMapper.deleteRolesById(roleId);
        //删除角色
        this.baseMapper.deleteById(roleId);
    }

    public BaseResponse roleList() {
        List<GopRole> gopRoleList = this.list();
        List<GopRole> result = PageWithSqlUtil.getList(gopRoleList, GopRole.class);
        List<GopRoleResult> gopRoleResultList = EntityConvertUtils.convertAListToBList(result, GopRoleResult.class);
        for (GopRoleResult roleResult : gopRoleResultList) {
            List<GopMenu> gopMenuList = menuService.getRelationsByRoleId(roleResult.getId());
            List<String> menuNames = gopMenuList.stream().map(GopMenu::getName).collect(Collectors.toList());
            List<Long> menuIds = gopMenuList.stream().map(GopMenu::getId).collect(Collectors.toList());
            roleResult.setMenuNames(menuNames);
            roleResult.setMenuIds(menuIds);
        }
        return BaseResponse.success("角色列表获取成功", gopRoleResultList, gopRoleList.size());
    }

    public GopRole queryUnInValidByRoleId(Long roleId) {
        List<GopRole> gopRoleList = this.queryUnInValidByRoleIds(Arrays.asList(roleId));
        if (ToolUtil.isNotEmpty(gopRoleList)) {
            return gopRoleList.get(0);
        } else {
            return null;
        }
    }

    public List<GopRole> queryUnInValidByRoleIds(List<Long> roleIds) {
        LambdaQueryWrapper<GopRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(GopRole::getId, roleIds);
        queryWrapper.eq(GopRole::getIsInvalid, false);
        return list(queryWrapper);
    }

    public String queryByRoleId(Long roleId) {
        if (ToolUtil.isEmpty(roleId)) {
            return "";
        }
        LambdaQueryWrapper<GopRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GopRole::getId, roleId);
        queryWrapper.last("limit 1");
        queryWrapper.eq(GopRole::getIsInvalid, false);
        GopRole role = this.getOne(queryWrapper);
        if (ToolUtil.isNotEmpty(role)) {
            return role.getName();
        } else {
            return "";
        }
    }
}
